/////////////////////////////////////////////////////////////////////////////
// Copyright(c) 2012-2015 purang All Rights Reserved
// Name:        buffer_wrapper.h
// Purpose:     
// Author:      syy
// Modified by: 
// Created:     2014/9/2 16:27
// RCS-ID:      
// Licence:     
/////////////////////////////////////////////////////////////////////////////
#ifndef _BUFFER_WRAPPER_H_
#define _BUFFER_WRAPPER_H_
#include <vector>
#include <string.h>
#include "core/system/critical_section_wrapper.h"

namespace qb
{

	inline void __memcpy(void* pDst, uint32_t dwDstSize, void* pScr, uint32_t dwCpSize )
	{
#ifdef _MSC_VER
		memcpy_s(pDst,dwDstSize,pScr,dwCpSize);
#else
		memcpy(pDst, pScr, dwCpSize>dwDstSize?dwDstSize:dwCpSize);
#endif
	}

#define bcopy(s,d,ss)				__memcpy(d,ss,(void *)s,ss)
	const uint32_t trunkSize			= 64 * 1024;

	template <typename _type>
	class CBufferWrapper
	{
	public:
		CBufferWrapper()
			: _critSect(*CriticalSectionWrapper::CreateCriticalSection())
			, _maxSize(0)
			, _offPtr(0)
			, _currPtr(0)
		{
		}

		virtual ~CBufferWrapper()
		{
			delete &_critSect;
		}

		inline void enter()
		{
			_critSect.Enter();
		}

		inline void leave()
		{
			_critSect.Leave();
		}

		inline void put(const char *buf,const uint32_t size)
		{
			wr_reserve(size);
			bcopy(buf,&_buffer[_currPtr],size);
			_currPtr += size;
		}

		inline char *wr_buf()
		{
			return &_buffer[_currPtr];
		}

		inline char *rd_buf()
		{
			return &_buffer[_offPtr];
		}

		inline bool rd_ready()
		{
			bool ret = _currPtr > _offPtr;
			return ret;
		}

		inline uint32_t rd_size()
		{
			uint32_t ret = _currPtr - _offPtr;
			return ret;
		}

		inline void rd_flip(uint32_t size)
		{	
			if( size == 0 )
			{
				return;
			}
			_offPtr += size;
			if (_currPtr > _offPtr)
			{
				uint32_t tmp = _currPtr - _offPtr;
				if (_offPtr >= tmp)
				{
					memmove(&_buffer[0],&_buffer[_offPtr],tmp);
					_offPtr = 0;
					_currPtr = tmp;
				}
			}
			else
			{
				_offPtr = 0;
				_currPtr = 0;
			}
		}

		inline uint32_t wr_size()
		{
			uint32_t ret = _maxSize - _currPtr;
			return ret;
		}

		inline void wr_flip(const uint32_t size)
		{
			_currPtr += size;
		}

		inline void reset()
		{
			_offPtr = 0;
			_currPtr = 0;
		}

		inline uint32_t maxSize() const
		{
			return _maxSize;
		}

		inline void wr_reserve(const uint32_t size);

	private:
		CriticalSectionWrapper&	_critSect;
		uint32_t				_maxSize;
		uint32_t				_offPtr;
		uint32_t				_currPtr;
		_type					_buffer;
	};

	typedef CBufferWrapper<std::vector<char> > BufferQueue;

	template <>
	inline void BufferQueue::wr_reserve(const uint32_t size)
	{
		if (wr_size() < size)
		{
#define trunkCount(size) (((size) + trunkSize - 1) / trunkSize)
			_maxSize += (trunkSize * trunkCount(size));
			_buffer.resize(_maxSize);
		}
	}

}

#endif // _BUFFER_WRAPPER_H_
